package com.cazj.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cazj.common.exception.ServiceException;
import com.cazj.common.util.ShiroUtils;
import com.cazj.dao.LeaveBillDao;
import com.cazj.pojo.LeaveBill;
import com.cazj.service.WorkflowService;

import io.micrometer.core.instrument.util.StringUtils;

/**
 * 这是一个关于《工作流》处理相关的的实现接口类
 * @author 肖冲
 *
 */

@Service
public class WorkflowServiceImpl implements WorkflowService {

	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private RuntimeService runtimeService;
	@Autowired 
	private TaskService taskService;
	@Autowired
	private FormService formService;
	@Autowired
	private HistoryService historyService;

	SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");

	@Autowired
	private LeaveBillDao leaveBillDao;

	//保存新建的请假单
	@Override
	public void saveLeaveBill(LeaveBill leaveBill) {
		if(StringUtils.isEmpty(leaveBill.getUsername()))throw new IllegalArgumentException("请假人 不能为空");
		if(leaveBill.getLeaveDays()==null||leaveBill.getLeaveDays()<1)throw new IllegalArgumentException("请假天数 不能为空");
		if(leaveBill.getTypeId()==null||leaveBill.getTypeId()<1)throw new IllegalArgumentException("请假类型 不能为空");
		int rows = leaveBillDao.saveLeaveBill(leaveBill);
		if(rows<1)throw new ServiceException("保存请假单失败");

	}

	@Override
	public List<LeaveBill> findLeaveBillList() {

		return leaveBillDao.findLeaveBillList();
	}

	@Override
	public void deleteLeaveBillById(Integer workflowId) {
		if(workflowId==null||workflowId<0)throw new IllegalArgumentException("请假id参数 不能为空");
		int rows=leaveBillDao.deleteLeaveBillById(workflowId);
		if(rows<1)throw new ServiceException("删除请假单失败");
	}

	@Transactional
	@Override
	public void startLeaveBillProcess(Integer workflowId) {
		if(workflowId==null||workflowId<0)throw new IllegalArgumentException("请假id参数 不能为空");
		//获取请假单id,查询请假单对象.
		LeaveBill leaveBill=leaveBillDao.findLeaveBillById(workflowId);
		//更新请假单状态state 从0-->1
		leaveBill.setState(1);
		int rows=leaveBillDao.changeLeaveBillStateById(leaveBill);
		//使用当前对象的类名,作为流程图中的key,间接启动流程
		String key=leaveBill.getClass().getSimpleName();
		//使用key启动流程实例

		/**
		 * 4：从Session中获取当前任务的办理人，使用流程变量设置下一个任务的办理人
		 * inputUser是流程变量的名称，
		 * 获取的办理人是流程变量的值
		 */
		Map<String, Object> variables = new HashMap<String,Object>();
		variables.put("inputUser", ShiroUtils.getEmpName());//表示惟一用户


		/**
		 * 5：	(1)使用流程变量设置字符串（格式：LeaveBill.id的形式），通过设置，让启动的流程（流程实例）关联业务, 这个LeaveBill表中就可以对应得上这条记录
   				(2)使用正在执行对象表中的一个字段BUSINESS_KEY（Activiti提供的一个字段），让启动的流程（流程实例）关联业务
		 */
		String businessKey = key+"."+workflowId;
		variables.put("objId", businessKey);
		runtimeService.startProcessInstanceByKey(key, businessKey, variables);

	}
	//<需我处理>的页面呈现, 需要查询的是acvitivi中,runtimeservice任务列表.
	@Override
	public List<Map<String,Object>> findTaskListByName(String assignee) {

		List<Task> list = taskService.createTaskQuery()//
				.taskAssignee(assignee)//指定个人任务查询
				.orderByTaskCreateTime().asc()//
				.list();
		
		List<Map<String,Object>> listMap = new ArrayList<>();
		
		//activiti使用很多懒加载的概念, 导致list集合回传到controller的前端时, 无法封状成json数据, 需要在这里就要把list对象转成map对象. 再回传
		for (Task task : list) {
			Map<String, Object> map=new HashMap<>();
			map.put("id", task.getId());
			map.put("name", task.getName());
			map.put("createTime", sdf.format(task.getCreateTime()));
			map.put("assignee", task.getAssignee());
			//通过任务,拿到流程定义ID,
			String processDefinitionId = task.getProcessDefinitionId();
			//通过流程定义ID,,创建流程定义查询, 获得布署对象
			ProcessDefinition defProc = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
			//布署对象, 拿到部署ID
			String deploymentId = defProc.getDeploymentId();
			//部署ID,拿 到部署名称
			Deployment dep = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
			//System.out.println("deploy_name"+dep.getName());
			//将部署名称也返回到前端
			map.put("deployName", dep.getName());
			
			listMap.add(map);
		}
		
		return listMap;
		
	}

}
